/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ClientRMI;

import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
//import java.util.ArrayList;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import shared.*;

public class RMIClient {

    private String nick = "";
    private RMIInterface remoteObject;   // referencja do zdalnego obiektu
    private VectorClock vClock;
    private boolean IsLogIn = false;
    int myNumber;
    int losowy = -1;
    int vecNumber = 0;
    int CLI_NR = 5;
    private int[] decyzja = new int[CLI_NR];
    int[][] wybor = new int[CLI_NR][CLI_NR];
    String whoAmI = "";
    private int MAX_RANDOM = 1000;
    boolean firstStage = false;
    boolean secondStage = false;
    boolean podsumowanie = false;
    boolean xsend = true;
    boolean gettable = false;
    boolean only_once = false;
    int[] ile = new int[MAX_RANDOM];
    boolean start_all = false;

    public void login(String ip, String znick) throws RemoteException, NotBoundException {
        nick = znick;

        Registry reg = LocateRegistry.getRegistry(ip, 12345);
        remoteObject = (RMIInterface) reg.lookup("RMIServer");

        RMILogger.add("Zdarzenie : logowanie gracza : " + nick);
        RMIPair<Integer, VectorClock> temp = remoteObject.Login(nick);

        myNumber = temp.getFirst();
        vClock = new VectorClock(temp.getFirst());
        vClock.update(temp.getSecond());
        IsLogIn = true;

    }

    public void logout() throws RemoteException {
        RMILogger.add("Zdarzenie : wylogowanie gracza : " + nick);
        vClock.increment();
        VectorClock temp = remoteObject.Logout(nick, vClock);
        vClock.update(temp);
        IsLogIn = false;
    }

    public void start(final MyGraphicsView graphicsView, final JTable tableWidget, final JLabel decision) throws NotBoundException {

        Timer timer = new Timer();

        for (int i = 0; i < CLI_NR; i++) {
            decyzja[i] = -1;
        }
//        decyzja[myNumber] = losowy;
        // System.out.println("A " + myNumber + " " + losowy);

        timer.scheduleAtFixedRate(new TimerTask() {

            Random generator = new Random();

            public void run() {

                try {
                    if (IsLogIn) {
                        RMILogger.add("Zdarzenie : wysylanie wcisnietych klawiszy gracza : " + nick);
                        vClock.increment();
                        VectorClock temp = remoteObject.SendPositions(nick, graphicsView.player.moveLeft, graphicsView.player.moveRight, graphicsView.player.moveUp, graphicsView.player.moveDown,
                                graphicsView.player.shoot, graphicsView.mouseX, graphicsView.mouseY, vClock);
                        vClock.update(temp);

                        RMILogger.add("Zdarzenie : odbieranie pozycji graczy");
                        vClock.increment();
                        RMIPair<CopyOnWriteArrayList<Player>, VectorClock> pair1 = remoteObject.GetPlayersPos(vClock);
                        graphicsView.playersList = pair1.getFirst();
                        vClock.update(pair1.getSecond());

                        RMILogger.add("Zdarzenie : odbieranie pozycji pociskow");
                        vClock.increment();
                        RMIPair<CopyOnWriteArrayList<Bullet>, VectorClock> pair2 = remoteObject.GetBulletsPos(vClock);
                        graphicsView.bulletsList = pair2.getFirst();
                        vClock.update(pair2.getSecond());

                    }


                    DefaultTableModel model = (DefaultTableModel) tableWidget.getModel();

                    // czyszczenie zawartosci tablicy
                    for (int k = 0; k < tableWidget.getRowCount(); k++) {
                        for (int j = 0; j < 3; j++) {
                            model.setValueAt("", k, j);
                        }
                    }

                    model.setValueAt("- server -", 0, 0);
                    model.setValueAt("-", myNumber, 3);
                    for (Player play : graphicsView.playersList) {
                        model.setValueAt(play.nick, play.number, 0);
                        model.setValueAt(play.fragsNr, play.number, 1);
                        model.setValueAt(play.deathsNr, play.number, 2);
                    }

                    // odbierz komunikaty o liczebnosci
                    if (!firstStage && start_all) {

                        RMIPair<Integer, Integer> obj = remoteObject.GetInfo(myNumber);
                        if (obj.getFirst() != -1) {
                            decyzja[obj.getFirst()] = obj.getSecond();
                            vecNumber = remoteObject.GetNodesNr();
                            model.setValueAt(obj.getSecond(), obj.getFirst(), 3);
                        }
                        decyzja[myNumber] = losowy;

                        // sprawdz, czy mozna juz przeslac swoja tablice z decyzjami
                        firstStage = true;
                        secondStage = true;
                        for (int i = 0; i < vecNumber; i++) {
                            if (decyzja[i] <= 0) {
                                firstStage = false;
                                secondStage = false;
                                break;
                            }
                        }

                        if (vecNumber < 2) {
                            firstStage = false;
                            secondStage = false;
                        }
                    }
                    if (secondStage) {
                        // przeslij swoja tablice z decyzjami

                        if (xsend) {
                            //System.out.println("kto : " + myNumber + " " + whoAmI);
                            remoteObject.SendTableToRestNodes(myNumber, decyzja, whoAmI);
                            wybor[myNumber] = decyzja;
                            xsend = false;
                            gettable = true;
                        }

                        if (gettable) {
                            RMIPair<Integer, int[]> obj2 = remoteObject.GetTable(myNumber);

                            if (obj2.getFirst() != -1) {
                                wybor[obj2.getFirst()] = obj2.getSecond();
                            }


                            // sprawdz, czy mozna juz wyswietlac
                            secondStage = false;
                            podsumowanie = true;
                            for (int i = 0; i < vecNumber; i++) {
                                for (int j = 0; j < vecNumber; j++) {
                                    if (wybor[i][j] <= 0) {
                                        secondStage = true;
                                        podsumowanie = false;
                                        break;
                                    }
                                }
                            }

                        }
                    }

                    if (podsumowanie) {
                        /*System.out.println("otrzymalem ( " + myNumber);
                        for (int i = 0; i < vecNumber; i++) {
                            System.out.print("wek " + i + ": ");
                            for (int j = 0; j < vecNumber; j++) {
                                System.out.print(wybor[i][j] + " ");
                            }
                            System.out.println("\n");
                        }
*/

                        String label_wynik = "Otrzymano : ";
                        int max_index;
                        String max_s;
                        for (int i = 0; i < vecNumber; i++) {
                            for (int j = 0; j < vecNumber; j++) {
                                if (j != myNumber) {
                                    ile[wybor[j][i]]++;
                                }
                            }

                            max_index = 0;
                            max_s = Integer.toString(0);
                            for (int j = 1; j < MAX_RANDOM; j++) {
                                if (ile[j] > ile[max_index]) {
                                    max_index = j;
                                    max_s = Integer.toString(j);
                                }
                            }

                            for (int j = 0; j < MAX_RANDOM; j++) {
                                if (ile[j] == ile[max_index] && j != max_index) {
                                    max_s = "X";
                                    break;
                                }
                            }

                            // zaznacz
                            label_wynik += max_s + " ";

                            for (int j = 0; j < MAX_RANDOM; j++) {
                                ile[j] = 0;
                            }
                        }

                        decision.setText(label_wynik);
                        podsumowanie = false;
                    }

                    graphicsView.repaint();

                } catch (RemoteException ex) {
                    Logger.getLogger(RMIClient.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }, 0, 50);

    }

    // wyslij wszystkim pozostalym klientom
    void Send(int info, String whoami) throws RemoteException {
        whoAmI = whoami;
        remoteObject.SendInfoToRestNodes(myNumber, info, whoami);
        start_all = true;
    }
}
